<?php

namespace services\statistics;

use common\models\base\Project;
use common\models\clinic\Clinic;
use common\models\patient\RevisitingRecord;
use common\models\statistics\FollowReport;
use Yii;
use common\helpers\DateHelper;
use common\models\clinic\UserTreatment;
use common\models\member\Attr;
use common\models\member\Member;
use common\models\patient\User;
use common\components\Service;
use Exception;


class FollowReportService extends Service
{
    /**
     * 获取跟进列表
     *
     * @author wangxiang
     * @param array $condition
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getFollowList(array $condition, int $page = 0, int $pageSize = 0): array
    {
        $query = User::find()
            ->alias('p')
            ->leftJoin(RevisitingRecord::tableName() . ' r', 'p.patient_card_id = r.patient_card_id AND p.project_id = ' . $condition['project_id'])
            ->leftJoin(Clinic::tableName() . ' c', 'c.id = r.clinic_id')
            ->select([
                'p.id pid', 'p.name', 'p.age', 'p.gender', 'c.name clinic_name', 'r.clinic_id',
                'GROUP_CONCAT(r.revisting_time)  AS recently_clinic_times'
            ])
            ->where([
                'r.project_id' => $condition['project_id'],
                'is_sum' => RevisitingRecord::IS_SUM_YES
            ])
            ->andWhere(['between', 'r.revisting_time', $condition['start_time'], $condition['end_time']])
            ->groupBy([
                'r.patient_card_id', 'r.clinic_id'
            ]);


        // 权限验证
        if (Member::IS_SUPER_NO == Yii::$app->user->identity->member->is_super) {
            $memberId = Yii::$app->user->identity->member_id;
            $attr = Yii::$app->services->attr->findInfo([
                'member_id' => $memberId,
                'project_id' => $condition['project_id'],
            ]);
            if (!$attr) {
                return [];
            }
            if (Attr::IS_DEPARTMENT_LEADER_NO == $attr->is_department_leader) {// 普通员工【自己】
                $query->andWhere(['p.belong_assistant_id' => $memberId]);
            } else if (Attr::IS_DEPARTMENT_LEADER_YES == $attr->is_department_leader) {// 部门负责人【部门下所有员工】
                $memberIdData = Attr::find()
                    ->where([
                        'department_id' => $attr->department_id,
                        'project_id' => $condition['project_id']
                    ])
                    ->select('member_id')
                    ->column();
                $query->andWhere(['p.belong_assistant_id' => $memberIdData]);
            }
        }

        // 关键词搜索
        if (isset($condition['keyword']) && $condition['keyword']) {
            // 验证是否是手机号
            if (preg_match("/^1\d{10}$/", $condition['keyword'])) {
                $query->andWhere(['p.mobile' => $condition['keyword']]);
            } else {
                $query->andWhere([
                    'or',
                    ['like', 'p.name', $condition['keyword']],
                    ['p.patient_card_id' => $condition['keyword']]
                ]);
            }
        }

        // 诊室搜索
        isset($condition['clinic_id']) && $condition['clinic_id'] && $query->andWhere(['r.clinic_id' => $condition['clinic_id']]);

        // 医助搜索
        isset($condition['belong_assistant_id']) && $condition['belong_assistant_id'] && $query->andWhere((['p.belong_assistant_id' => $condition['belong_assistant_id']]));

        // 总数
        $total = $query->count();
        // 分页
        if ($page && $pageSize) {
            $query->limit($pageSize)->offset(($page - 1) * $pageSize);
        }
        $list = [];
        $data = $query
            ->orderBy(['p.last_revisiting_time' => SORT_DESC])
            ->asArray()
            ->all();

        // 处理数据
        foreach ($data as $item) {
            $tempArr = [
                'id' => $item['pid'],
                'info' => $item['name'] . ' ' . (User::$genders[$item['gender']] ?? '未知') . ' ' . $item['age'] . '岁',
                'clinic_name' => $item['clinic_name'],
            ];
            // 统计个月份的就诊次数
            for ($i = 1; $i <= 12; $i++) {
                $timeArr = array_filter(explode(',', $item['recently_clinic_times']));
                $tempArr['month_total'] = count($timeArr);
                $tempArr['month_' . $i] = 0;
                $timeArea = DateHelper::aMonth(date('Y', $condition['start_time']), $i);
                foreach ($timeArr as $time) {
                    if ($time >= $timeArea['start'] && $time <= $timeArea['end']) {
                        $tempArr['month_' . $i] += 1;
                    }
                }
            }

            $list[] = $tempArr;
        }

        return [
            'page' => (int)$page,
            'pageSize' => (int)$pageSize,
            'total' => (int)$total,
            'list' => $list,
        ];
    }


    /**
     * 获取跟进报表数据
     *
     * @author wangxiang
     * @param array $condition
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getFollowReport(array $condition, int $page = 0, int $pageSize = 0): array
    {
        $query = FollowReport::find()
            ->alias('f')
            ->leftJoin(User::tableName() . ' p', 'p.id = f.patient_id')
            ->leftJoin(Clinic::tableName() . ' c', 'c.id = f.clinic_id')
            ->where([
                'p.project_id' => $condition['project_id'],
                'p.status' => [User::STATUS_INVALID, User::STATUS_ENABLE],
                'f.year' => $condition['year']
            ])
            ->select([
                'f.*', 'c.name clinic_name', 'p.name', 'p.age', 'p.gender'
            ]);

        // 关键词搜索
        if (isset($condition['keyword']) && $condition['keyword']) {
            // 验证是否是手机号
            if (preg_match("/^1\d{10}$/", $condition['keyword'])) {
                $query->andWhere(['p.mobile' => $condition['keyword']]);
            } else {
                $query->andWhere([
                    'or',
                    ['p.patient_card_id' => $condition['keyword']],
                    ['like', 'p.name', $condition['keyword']]
                ]);
            }
        }

        // 诊室搜索
        isset($condition['clinic_id']) && $condition['clinic_id'] && $query->andWhere(['p.clinic_id' => $condition['clinic_id']]);

        // 医助搜索
        isset($condition['belong_assistant_id']) && $condition['belong_assistant_id'] && $query->andWhere((['p.belong_assistant_id' => $condition['belong_assistant_id']]));

        // 权限验证
        if (Member::IS_SUPER_NO == Yii::$app->user->identity->member->is_super) {
            $memberId = Yii::$app->user->identity->member_id;
            $attr = Yii::$app->services->attr->findInfo([
                'member_id' => $memberId,
                'project_id' => $condition['project_id'],
            ]);
            if (!$attr) {
                return [];
            }
            if (Attr::IS_DEPARTMENT_LEADER_NO == $attr->is_department_leader) {// 普通员工【自己】
                $query->andWhere(['p.belong_assistant_id' => $memberId]);
            } else if (Attr::IS_DEPARTMENT_LEADER_YES == $attr->is_department_leader) {// 部门负责人【部门下所有员工】
                $memberIdData = Attr::find()
                    ->where([
                        'department_id' => $attr->department_id,
                        'project_id' => $condition['project_id']
                    ])
                    ->select('member_id')
                    ->column();
                $query->andWhere(['p.belong_assistant_id' => $memberIdData]);
            }
        }

        // 判断排序
        if (isset($condition['sort']) && isset($condition['sort_field']) && $condition['sort'] && $condition['sort_field']) {
            if ($condition['sort'] == 1) {
                // 正序
                $query->orderBy([
                    'f.' . $condition['sort_field'] => SORT_ASC,
                    'p.last_revisiting_time' => SORT_DESC
                ]);
            } else {
                // 倒序
                $query->orderBy([
                    'f.' . $condition['sort_field'] => SORT_DESC,
                    'p.last_revisiting_time' => SORT_DESC
                ]);
            }
        } else {
            $query->orderBy([
                'p.last_revisiting_time' => SORT_DESC
            ]);
        }

        // 总数
        $total = $query->count();
        // 分页
        if ($page && $pageSize) {
            $query->limit($pageSize)->offset(($page - 1) * $pageSize);
        }

        $data = $query
            ->asArray()
            ->all();

        return [
            'page' => (int)$page,
            'pageSize' => (int)$pageSize,
            'total' => (int)$total,
            'list' => $data,
        ];
    }


    /**
     * 格式化报表数据
     *
     * @author wangxiang
     * @param array $data
     * @return array
     */
    public function formatReport(array $data): array
    {
        $list = [];

        foreach ($data as $item) {
            $tempArr = [
                'id' => $item['patient_id'],
                'info' => $item['name'] . ' ' . (User::$genders[$item['gender']] ?? '未知') . ' ' . $item['age'] . '岁',
                'clinic_name' => $item['clinic_name'],
                'month_total' => (int)$item['month_total'],
            ];
            for ($i = 1; $i <= 12; $i++) {
                $tempArr['month_' . $i] = (int)$item['month_' . $i];
            }
            $list[] = $tempArr;
        }

        return $list;
    }


    /**
     * 生成跟进报表快照数据
     *
     * @author wangxiang
     * @param int $startTime
     * @param int $endTime
     * @param int $projectId
     * @param string $type
     * @throws Exception
     */
    public function generateReport(int $startTime, int $endTime, int $projectId = 0, $type = 'm'): void
    {
        if (!in_array($type, ['m', 'y'])) {
            throw new Exception('计划执行失败， 日期类型不正确！', 500);
        }
        if ($projectId) {
            $projectIdArr = [$projectId];
        } else {
            $projectIdArr = Project::find()->where(['status' => Project::STATUS_ENABLE])->select('id')->column();
        }
        // 记录执行失败的项目信息
        $errorArr = [];
        foreach ($projectIdArr as $projectId) {
            $query = User::find()
                ->alias('p')
                ->leftJoin(RevisitingRecord::tableName() . ' r', 'p.patient_card_id = r.patient_card_id AND p.project_id = ' . $projectId)
                ->leftJoin(Clinic::tableName() . ' c', 'c.id = r.clinic_id')
                ->select([
                    'p.id pid', 'p.name', 'p.age', 'p.gender', 'p.patient_card_id', 'c.name clinic_name', 'r.clinic_id',
                    'GROUP_CONCAT(r.revisting_time)  AS recently_clinic_times'
                ])
                ->where([
                    'p.status' => [User::STATUS_INVALID, User::STATUS_ENABLE],
                    'r.project_id' => $projectId,
                    'is_sum' => RevisitingRecord::IS_SUM_YES
                ])
                ->andWhere(['between', 'r.revisting_time', $startTime, $endTime])
                ->groupBy([
                    'r.patient_card_id', 'r.clinic_id'
                ]);

            $data = $query->asArray()->all();

            $transaction = Yii::$app->db->beginTransaction();
            try {
                foreach ($data as $item) {
                    $model = FollowReport::findOne(['year' => date('Y', $startTime), 'patient_id' => $item['pid'], 'clinic_id' => $item['clinic_id']]);
                    if (!$model) {
                        $model = new FollowReport;
                        $model->year = date('Y', $startTime);
                        $model->patient_id = $item['pid'];
                        $model->clinic_id = $item['clinic_id'];
                    }
                    // 来院时间记录
                    $timeArr = array_filter(explode(',', $item['recently_clinic_times']));
                    // 统计个月份的就诊次数
                    if ($type == 'y') {
                        $monthTotal = 0;
                        for ($i = 1; $i <= 12; $i++) {
                            $tempArr['month_' . $i] = 0;
                            $timeArea = DateHelper::aMonth(date('Y', $startTime), $i);
                            foreach ($timeArr as $k=> $time) {
                                if ($time >= $timeArea['start'] && $time <= $timeArea['end']) {
                                    $tempArr['month_' . $i] += 1;
                                    unset($timeArr[$k]);
                                }
                            }
                            $key = 'month_' . $i;
                            $model->$key = $tempArr['month_' . $i];
                            $monthTotal += $tempArr['month_' . $i];
                        }
                    } else if ($type == 'm') {
                        $key = 'month_' . date('n', $startTime);
                        $monthTotal = intval($model->month_total) + count($timeArr) - intval($model->$key);
                        $model->$key = count($timeArr);
                    } else {
                        throw new Exception('计划执行失败， 日期类型不正确！', 500);
                    }

                    $model->month_total = $monthTotal;
                    $model->saveAndCheckResult();
                }
                $transaction->commit();
                echo $projectId . PHP_EOL;
            } catch (Exception $exception) {
                $transaction->rollBack();
                $errorArr[] = [
                    'project_id' => $projectId,
                    'error_msg' => $exception->getMessage()
                ];
                continue;
            }

            if ($errorArr) {
                $msg = '';
                foreach ($errorArr as $error) {
                    $msg .= '执行错误项目：' . $error['project_id'] . PHP_EOL;
                    $msg .= '执行错误信息：' . $error['error_msg'] . PHP_EOL;
                }
                throw new Exception($msg, 500);
            }

        }

    }

}
